package com.edu.exam.entity.grading.query;

import com.edu.exam.enums.grading.AnalysisType;
import com.edu.exam.enums.grading.AnalysisStatus;
import com.edu.exam.enums.grading.AnalysisPrecision;
import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import java.time.LocalDateTime;

/**
 * 成绩分析结果表实体类
 *
 * <p>所属模块：B-06 成绩管理模块</p>
 * <p>对应数据库表：grade_analysis_result</p>
 *
 * <p>成绩分析结果表实体用于存储成绩分析的结果数据，包含
 * 分析类型、分析条件、分析结果、状态信息等。为成绩分析功能提供完整的结果存储和管理。</p>
 *
 * <p>核心功能：
 * - 分析结果存储：存储各种类型成绩分析的结果数据
 * - 分析条件记录：记录生成分析结果的条件和参数
 * - 状态管理：管理分析结果的生成状态和有效性
 * - 版本控制：支持分析结果的版本管理和历史追踪
 * - 过期管理：控制分析结果的有效期和自动失效</p>
 *
 * @author 系统生成
 * @version 1.0
 * @since 2025-11-10
 */
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Entity
@EntityListeners(AuditingEntityListener.class)
public class GradeAnalysisResult {

    /**
     * 主键ID
     */
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    /**
     * 分析类型
     *
     * <p>分析的类型标识。</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "analysis_type", nullable = false, length = 30)
    private AnalysisType analysisType;

    /**
     * 分析条件
     *
     * <p>分析的条件和参数，JSON格式存储。</p>
     */
    @Lob
    @Column(name = "analysis_condition", columnDefinition = "LONGTEXT")
    private String analysisCondition;

    /**
     * 分析结果
     *
     * <p>分析的结果数据，JSON格式存储。</p>
     */
    @Lob
    @Column(name = "analysis_result", columnDefinition = "LONGTEXT")
    private String analysisResult;

    /**
     * 分析状态
     *
     * <p>分析的当前状态。</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "analysis_status", nullable = false, length = 20)
    @Builder.Default
    private AnalysisStatus analysisStatus = AnalysisStatus.PENDING;

    /**
     * 数据版本
     *
     * <p>分析结果的版本号。</p>
     */
    @Column(name = "data_version", length = 20)
    @Builder.Default
    private String dataVersion = "1.0";

    /**
     * 过期时间
     *
     * <p>分析结果的过期时间。</p>
     */
    @Column(name = "expire_time")
    private LocalDateTime expireTime;

    /**
     * 是否过期
     *
     * <p>标记分析结果是否已过期。</p>
     */
    @Column(name = "is_expired", nullable = false)
    @Builder.Default
    private Boolean isExpired = false;

    /**
     * 分析开始时间
     *
     * <p>分析计算开始的时间。</p>
     */
    @Column(name = "analysis_start_time")
    private LocalDateTime analysisStartTime;

    /**
     * 分析完成时间
     *
     * <p>分析计算完成的时间。</p>
     */
    @Column(name = "analysis_end_time")
    private LocalDateTime analysisEndTime;

    /**
     * 分析耗时
     *
     * <p>分析计算的总耗时，单位毫秒。</p>
     */
    @Column(name = "analysis_duration_ms")
    private Long analysisDurationMs;

    /**
     * 数据样本数量
     *
     * <p>分析使用的数据样本数量。</p>
     */
    @Column(name = "sample_count")
    private Integer sampleCount;

    /**
     * 数据范围
     *
     * <p>分析数据的范围描述。</p>
     */
    @Column(name = "data_scope", length = 200)
    private String dataScope;

    /**
     * 时间范围
     *
     * <p>分析数据的时间范围。</p>
     */
    @Column(name = "time_range", length = 100)
    private String timeRange;

    /**
     * 分析精度
     *
     * <p>分析结果的精度级别。</p>
     */
    @Enumerated(EnumType.STRING)
    @Column(name = "analysis_precision", length = 20)
    private AnalysisPrecision analysisPrecision;

    /**
     * 置信度
     *
     * <p>分析结果的置信度（0-1）。</p>
     */
    @Column(name = "confidence_level", precision = 3, scale = 2)
    private Double confidenceLevel;

    /**
     * 错误信息
     *
     * <p>分析失败时的错误信息。</p>
     */
    @Column(name = "error_message", columnDefinition = "TEXT")
    private String errorMessage;

    /**
     * 警告信息
     *
     * <p>分析过程中的警告信息。</p>
     */
    @Column(name = "warning_message", columnDefinition = "TEXT")
    private String warningMessage;

    /**
     * 分析算法
     *
     * <p>使用的分析算法类型。</p>
     */
    @Column(name = "analysis_algorithm", length = 50)
    private String analysisAlgorithm;

    /**
     * 分析模型
     *
     * <p>使用的分析模型信息。</p>
     */
    @Column(name = "analysis_model", length = 100)
    private String analysisModel;

    /**
     * 分析参数
     *
     * <p>分析算法的参数配置，JSON格式存储。</p>
     */
    @Column(name = "analysis_parameters", columnDefinition = "TEXT")
    private String analysisParameters;

    /**
     * 质量评分
     *
     * <p>分析结果的质量评分（0-100）。</p>
     */
    @Column(name = "quality_score")
    private Integer qualityScore;

    /**
     * 可信度评分
     *
     * <p>分析结果的可信度评分（0-100）。</p>
     */
    @Column(name = "reliability_score")
    private Integer reliabilityScore;

    /**
     * 完整性评分
     *
     * <p>分析结果的完整性评分（0-100）。</p>
     */
    @Column(name = "completeness_score")
    private Integer completenessScore;

    /**
     * 准确性评分
     *
     * <p>分析结果的准确性评分（0-100）。</p>
     */
    @Column(name = "accuracy_score")
    private Integer accuracyScore;

    /**
     * 分析标签
     *
     * <p>分析结果的分类标签。</p>
     */
    @Column(name = "analysis_tags", length = 500)
    private String analysisTags;

    /**
     * 关键发现
     *
     * <p>分析过程中的关键发现，JSON格式存储。</p>
     */
    @Column(name = "key_findings", columnDefinition = "TEXT")
    private String keyFindings;

    /**
     * 建议
     *
     * <p>基于分析结果的建议，JSON格式存储。</p>
     */
    @Column(name = "recommendations", columnDefinition = "TEXT")
    private String recommendations;

    /**
     * 限制条件
     *
     * <p>分析的限制条件和假设，JSON格式存储。</p>
     */
    @Column(name = "limitations", columnDefinition = "TEXT")
    private String limitations;

    /**
     * 附加数据
     *
     * <p>附加的分析数据，JSON格式存储。</p>
     */
    @Column(name = "additional_data", columnDefinition = "TEXT")
    private String additionalData;

    // ===== 审计字段 =====

    /**
     * 创建时间
     */
    @CreatedDate
    @Column(name = "create_time", nullable = false, updatable = false)
    private LocalDateTime createTime;

    /**
     * 更新时间
     */
    @LastModifiedDate
    @Column(name = "update_time", nullable = false)
    private LocalDateTime updateTime;

    /**
     * 创建人ID
     */
    @Column(name = "creator_id")
    private Long creatorId;

    /**
     * 分析失败
     *
     * @param errorMessage 错误信息
     */
    public void failAnalysis(String errorMessage) {
        this.analysisStatus = AnalysisStatus.FAILED;
        this.errorMessage = errorMessage;
        
        // 设置默认的质量评分
        this.qualityScore = 0;
    }

    /**
     * 检查分析是否完成
     *
     * @return 如果分析完成返回true，否则返回false
     */
    public boolean isAnalysisCompleted() {
        return analysisStatus == AnalysisStatus.COMPLETED;
    }

    /**
     * 检查分析是否失败
     *
     * @return 如果分析失败返回true，否则返回false
     */
    public boolean isAnalysisFailed() {
        return analysisStatus == AnalysisStatus.FAILED;
    }

    /**
     * 检查分析是否过期
     *
     * @return 如果分析过期返回true，否则返回false
     */
    public boolean isAnalysisExpired() {
        if (Boolean.TRUE.equals(isExpired)) {
            return true;
        }

        if (expireTime != null) {
            return LocalDateTime.now().isAfter(expireTime);
        }

        return false;
    }

    /**
     * 检查分析是否有效
     *
     * @return 如果分析有效返回true，否则返回false
     */
    public boolean isAnalysisValid() {
        return isAnalysisCompleted() &&
               !isAnalysisExpired() &&
               !Boolean.TRUE.equals(isExpired) &&
               analysisResult != null &&
               !analysisResult.trim().isEmpty();
    }

    /**
     * 设置分析结果评分
     *
     * @param qualityScore 质量评分
     * @param reliabilityScore 可信度评分
     * @param completenessScore 完整性评分
     * @param accuracyScore 准确性评分
     */
    public void setAnalysisScores(Integer qualityScore, Integer reliabilityScore,
                                Integer completenessScore, Integer accuracyScore) {
        this.qualityScore = qualityScore;
        this.reliabilityScore = reliabilityScore;
        this.completenessScore = completenessScore;
        this.accuracyScore = accuracyScore;
    }

    /**
     * 添加分析标签
     *
     * @param tag 分析标签
     */
    public void addAnalysisTag(String tag) {
        if (tag == null || tag.trim().isEmpty()) {
            return;
        }

        String currentTags = this.analysisTags;
        if (currentTags == null || currentTags.trim().isEmpty()) {
            this.analysisTags = tag;
        } else {
            if (!currentTags.contains(tag)) {
                this.analysisTags = currentTags + "," + tag;
            }
        }
    }

    /**
     * 检查是否有指定标签
     *
     * @param tag 分析标签
     * @return 如果有指定标签返回true，否则返回false
     */
    public boolean hasAnalysisTag(String tag) {
        return this.analysisTags != null && this.analysisTags.contains(tag);
    }

    /**
     * 获取分析类型显示名称
     *
     * @return 分析类型显示名称
     */
    public String getAnalysisTypeDisplayName() {
        return switch (analysisType) {
            case TREND_ANALYSIS -> "趋势分析";
            case DISTRIBUTION_ANALYSIS -> "分布分析";
            case COMPARISON_ANALYSIS -> "对比分析";
            case CORRELATION_ANALYSIS -> "相关性分析";
            case OUTLIER_ANALYSIS -> "异常值分析";
            case CLUSTER_ANALYSIS -> "聚类分析";
            case PREDICTIVE_ANALYSIS -> "预测分析";
            case REGRESSION_ANALYSIS -> "回归分析";
            case FACTOR_ANALYSIS -> "因子分析";
            case COMPREHENSIVE_EVALUATION -> "综合评价分析";
            case DIFFERENCE_ANALYSIS -> "差异分析";
            case EFFICIENCY_ANALYSIS -> "效能分析";
        };
    }

    /**
     * 获取分析状态显示名称
     *
     * @return 分析状态显示名称
     */
    public String getAnalysisStatusDisplayName() {
        return switch (analysisStatus) {
            case PENDING -> "待分析";
            case ANALYZING -> "分析中";
            case COMPLETED -> "已完成";
            case FAILED -> "失败";
            case CANCELLED -> "已取消";
            case EXPIRED -> "已过期";
            case PARTIALLY_COMPLETED -> "部分完成";
        };
    }

    /**
     * 获取分析精度显示名称
     *
     * @return 分析精度显示名称
     */
    public String getAnalysisPrecisionDisplayName() {
        return switch (analysisPrecision) {
            case LOW -> "低精度";
            case MEDIUM -> "中等精度";
            case HIGH -> "高精度";
            case EXACT -> "精确";
            default -> "未知";
        };
    }

    /**
     * 格式化分析耗时
     *
     * @return 格式化的时间字符串
     */
    public String formatAnalysisDuration() {
        if (analysisDurationMs == null) {
            return "-";
        }

        long time = analysisDurationMs;
        if (time < 1000) {
            return time + "ms";
        } else if (time < 60 * 1000) {
            return String.format("%.1fs", time / 1000.0);
        } else {
            long minutes = time / (60 * 1000);
            long seconds = (time % (60 * 1000)) / 1000;
            return minutes + "m" + seconds + "s";
        }
    }

    /**
     * 获取分析摘要信息
     *
     * @return 分析摘要
     */
    public String getAnalysisSummary() {
        StringBuilder sb = new StringBuilder();
        sb.append("分析[").append(id);
        sb.append("] - ").append(getAnalysisTypeDisplayName());
        sb.append(" - ").append(getAnalysisStatusDisplayName());

        if (analysisPrecision != null) {
            sb.append(" - ").append(getAnalysisPrecisionDisplayName());
        }

        if (dataScope != null) {
            sb.append(" - 范围:").append(dataScope);
        }

        if (timeRange != null) {
            sb.append(" - 时间:").append(timeRange);
        }

        if (sampleCount != null) {
            sb.append(" - 样本:").append(sampleCount);
        }

        if (analysisDurationMs != null) {
            sb.append(" - 耗时:").append(formatAnalysisDuration());
        }

        Integer overallScore = calculateOverallScore();
        if (overallScore != null) {
            sb.append(" - 评分:").append(overallScore);
        }

        if (confidenceLevel != null) {
            sb.append(" - 置信度:").append(String.format("%.2f", confidenceLevel));
        }

        return sb.toString();
    }

    /**
     * 验证分析数据
     *
     * @return 验证结果
     */
    public boolean validateAnalysisData() {
        return analysisType != null &&
               analysisStatus != null &&
               createTime != null &&
               (analysisCondition == null || !analysisCondition.trim().isEmpty()) &&
               (sampleCount == null || sampleCount >= 0) &&
               (confidenceLevel == null || (confidenceLevel >= 0 && confidenceLevel <= 1)) &&
               (analysisDurationMs == null || analysisDurationMs >= 0);
    }

    /**
     * 检查是否为高质量分析
     *
     * @param threshold 质量阈值
     * @return 如果是高质量分析返回true，否则返回false
     */
    public boolean isHighQualityAnalysis(Integer threshold) {
        Integer overallScore = calculateOverallScore();
        return overallScore != null && threshold != null && overallScore >= threshold;
    }

    /**
     * 检查是否为可信分析
     *
     * @param threshold 可信度阈值
     * @return 如果是可信分析返回true，否则返回false
     */
    public boolean isReliableAnalysis(Double threshold) {
        return confidenceLevel != null && threshold != null && confidenceLevel >= threshold;
    }

    /**
     * 更新数据版本
     *
     * @param newVersion 新版本号
     */
    public void updateDataVersion(String newVersion) {
        this.dataVersion = newVersion;
    }

    /**
     * 重置分析状态
     *
     * <p>重置分析状态，准备重新分析。</p>
     */
    public void resetAnalysisStatus() {
        this.analysisStatus = AnalysisStatus.PENDING;
        this.analysisStartTime = null;
        this.analysisEndTime = null;
        this.analysisDurationMs = null;
        this.errorMessage = null;
        this.warningMessage = null;
        this.isExpired = false;
    }

    /**
     * 计算总体评分
     *
     * @return 总体评分，如果无法计算则返回null
     */
    public Integer calculateOverallScore() {
        // 简化的计算逻辑 - 实际项目中应根据具体业务规则实现
        if (confidenceLevel == null || sampleCount == null) {
            return null;
        }
        
        // 基础评分基于置信度（0-100分）
        double baseScore = confidenceLevel * 100;
        
        // 根据样本数量调整评分
        if (sampleCount > 1000) {
            baseScore *= 1.1; // 样本量大，增加10%权重
        } else if (sampleCount < 10) {
            baseScore *= 0.7; // 样本量小，减少30%权重
        }
        
        // 确保评分在合理范围内
        int finalScore = (int) Math.max(0, Math.min(100, baseScore));
        
        return finalScore;
    }
}